package com.ysstech.reportworld.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ysstech.common.cache.RedisCacheManager;
import com.ysstech.common.entity.TreeNode;
import com.ysstech.common.exception.BusinessException;
import com.ysstech.common.service.DicvalueService;
import com.ysstech.common.util.DateUtil;
import com.ysstech.reportworld.entity.Customer;
import com.ysstech.reportworld.entity.DataCustomer;
import com.ysstech.reportworld.enums.ReportWorldEnum;
import com.ysstech.reportworld.enums.ReportWorldStatusEnum;
import com.ysstech.reportworld.mapper.CustomerMapper;
import com.ysstech.reportworld.mapper.DataCustomerMapper;
import com.ysstech.reportworld.service.CustomerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 报表世界客户信息 服务实现类
 * </p>
 *
 * @author lishuangliang
 * @since 2022-04-28
 */
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {

    @Autowired
    private DataCustomerMapper dataCustomerMapper;
    @Autowired
    private DicvalueService dicvalueService;
    @Autowired
    private RedisCacheManager redisCacheManager;

    /**
     * 查询客户树信息
     *
     * @return
     */
    public List<TreeNode> queryCustomerTree() throws Exception {
        List<TreeNode> list = new ArrayList<>();
        List<Customer> listCustomer = this.list();
        if (CollectionUtils.isEmpty(listCustomer)) {
            return list;
        }
        list.addAll(this.recursionTree("0", listCustomer));
        return list;
    }

    private List<TreeNode> recursionTree(String orgId, List<Customer> listCustomer) throws Exception {
        List<TreeNode> list = new ArrayList<>();
        for (Customer customer : listCustomer) {
            if (!orgId.equals(customer.getParentId())) {
                continue;
            }
            TreeNode treeNode = ReportCustomerToNode(customer);
            List<TreeNode> children = recursionTree(customer.getId(), listCustomer);
            if (null == children || children.size() == 0) {
                treeNode.setState("open");
            } else {
                treeNode.setChildren(children);
            }
            list.add(treeNode);
        }
        return list;
    }

    /**
     * 将业务功能转化成TreeNode
     */
    private TreeNode ReportCustomerToNode(Customer customer) {
        TreeNode node = new TreeNode();
        node.setId(customer.getId());
        node.setText(customer.getName());
        node.setState("closed");
        node.setChecked(false);
        node.setIconCls("icon-bricks");
        node.setPId(customer.getParentId());
        return node;
    }


    /**
     * 获取客户信息
     *
     * @return
     * @throws Exception
     */
    public Map<String, Customer> getCustomerMap() throws Exception {
        Map<String, Customer> mapReportCustomer = new HashMap<>();
        List<Customer> listCustomer = list();
        if (CollectionUtils.isEmpty(listCustomer)) {
            return null;
        }
        for (Customer customer : listCustomer) {
            if (null == customer || StringUtils.isBlank(customer.getId())) {
                continue;
            }
            mapReportCustomer.put(customer.getId(), customer);
        }
        return mapReportCustomer;
    }


    /**
     * 查询所有下级客户的客户集合
     *
     * @param id 客户编号
     * @return
     * @throws Exception
     */
    public List<Customer> queryListReportCustomer(String id) throws Exception {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("获取客户信息失败，请稍后重试！");
        }
        List<String> list = this.queryCustomerIds(id);
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.in("ID", list);
        List<Customer> listCustomer = this.list(wrapper);
        return listCustomer;
    }

    /**
     * 查询所有下级客户的客户id集合
     *
     * @param id
     * @return
     * @throws Exception
     */
    public List<String> queryCustomerIds(String id) throws Exception {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("获取客户信息失败，请稍后重试！");
        }
        List<String> strList = new ArrayList<>();
        strList.add(id);
        List<Customer> list = this.list();
        recursionIds(id, strList, list);
        return strList;
    }

    private void recursionIds(String orgId, List<String> strList, List<Customer> list) {
        for (Customer customer : list) {
            if (!orgId.equals(customer.getParentId())) {
                continue;
            }
            strList.add(customer.getId());
            recursionIds(customer.getId(), strList, list);
        }
    }


    /**
     * 获取客户对应表信息
     *
     * @return
     */
    @Override
    public List<DataCustomer> getTableInfo(DataCustomer dataCustomer) throws Exception {
        if (null == dataCustomer || StringUtils.isBlank(dataCustomer.getCustomerId())) {
            throw new BusinessException("获取客户对应表信息失败，请稍后重试！");
        }
        List<DataCustomer> list = dataCustomerMapper.getTableInfo(dataCustomer);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        // 报表世界所在分层
        Map<String, String> mapTableLayered = dicvalueService.getCacheDicValueMap(ReportWorldEnum.REPORT_TABLE_LAYERED.getCode());
        // 表类型
        Map<String, String> mapFtype = dicvalueService.getCacheDicValueMap(ReportWorldEnum.REPORT_TABLE_FTYPE.getCode());
        // 表来源
        Map<String, String> maptFsource = dicvalueService.getCacheDicValueMap(ReportWorldEnum.REPORT_TABLE_FSOURCE.getCode());
        for (DataCustomer customer : list) {
            if (null == customer) {
                continue;
            }
            //报表世界所在分层
            if (null != mapTableLayered && mapTableLayered.containsKey(String.valueOf(customer.getLayered()))) {
                customer.setLayered(mapTableLayered.get(String.valueOf(customer.getLayered())));
            }
            //表类型
            if (null != mapFtype && mapFtype.containsKey(String.valueOf(customer.getFtype()))) {
                customer.setFtype(mapFtype.get(String.valueOf(customer.getFtype())));
            }
            //表来源
            if (null != maptFsource && maptFsource.containsKey(String.valueOf(customer.getFsource()))) {
                customer.setFsource(maptFsource.get(String.valueOf(customer.getFsource())));
            }

        }
        return list;
    }

    /**
     * 添加客户信息
     *
     * @param customer
     * @throws Exception
     */
    public void addCustomer(Customer customer) throws Exception {
        if (customer == null) {
            throw new BusinessException("获取模块信息失败，请稍后重试！");
        }
        String id = DateUtil.generateUUID();
        customer.setId(id);
        customer.setStatus(ReportWorldStatusEnum.REPORT_NORMAL.getCode());
        customer.setAddUser(redisCacheManager.getLoginUserInfo().getLoginId());
        customer.setAddTime(LocalDateTime.now());
        if ("0".equals(customer.getParentId())) {
            this.save(customer);
            return;
        }
        //添加之前没有下级模块的数据的 添加了以后 模块的关联关系修改到下级
        // 获取该模块的上级之前是不是最明细的
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.eq("PARENT_ID", customer.getParentId());
        List<Customer> list = this.list(wrapper);
        if (CollectionUtils.isEmpty(list)) { //添加的上级以前没有下级
            // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
            UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("CUSTOMER_ID", customer.getParentId());
            DataCustomer dataCustomer = new DataCustomer();
            dataCustomer.setCustomerId(id);
            dataCustomer.setStatus(ReportWorldStatusEnum.REPORT_NORMAL.getCode());
            dataCustomer.setAddUser(redisCacheManager.getLoginUserInfo().getLoginId());
            dataCustomer.setAddTime(LocalDateTime.now());
            dataCustomerMapper.update(dataCustomer, updateWrapper);
        }
        this.save(customer);
    }

    /**
     * 修改客户信息
     *
     * @param customer
     * @throws Exception
     */
    public void editCustomer(Customer customer) throws Exception {
        if (customer == null || StringUtils.isBlank(customer.getId())) {
            throw new BusinessException("获取模块信息失败，请稍后重试！");
        }
        // 修改之前的上级只有一个下级
        Customer oldCustomer = this.getById(customer.getId());
        QueryWrapper<Customer> wrapperOld = new QueryWrapper<>();
        wrapperOld.eq("PARENT_ID", oldCustomer.getId());
        List<Customer> listOld = this.list(wrapperOld);
        if (CollectionUtils.isEmpty(listOld)) { //修改之前没有下级
            QueryWrapper<Customer> wrapper = new QueryWrapper<>();
            wrapper.eq("PARENT_ID", oldCustomer.getParentId());
            List<Customer> list = this.list(wrapper);
            if (!CollectionUtils.isEmpty(list) && list.size() == 1) {
                // 原来的关联表是这个明细的ID 更新成现在将会变成明细的上级ID
                UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("CUSTOMER_ID", oldCustomer.getId());
                DataCustomer dataCustomer = new DataCustomer();
                dataCustomer.setCustomerId(oldCustomer.getParentId());
                dataCustomer.setStatus(ReportWorldStatusEnum.REPORT_NORMAL.getCode());
                dataCustomer.setAddUser(redisCacheManager.getLoginUserInfo().getLoginId());
                dataCustomer.setAddTime(LocalDateTime.now());
                dataCustomerMapper.update(dataCustomer, updateWrapper);
            }
        }
        customer.setEditUser(redisCacheManager.getLoginUserInfo().getLoginId());
        customer.setEditTime(LocalDateTime.now());
        //修改后的上级
        if ("0".equals(customer.getParentId())) {
            this.updateById(customer);
            return;
        }
        // 修改后的这上级 之前是否存在下级
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.eq("PARENT_ID", customer.getParentId());
        List<Customer> list = this.list(wrapper);
        if (CollectionUtils.isEmpty(list)) { //添加的上级以前没有下级
            // 将关联关系表中原来模块的数据，更新成现在这个新的下级菜单
            UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("CUSTOMER_ID", customer.getParentId());
            DataCustomer dataCustomer = new DataCustomer();
            dataCustomer.setCustomerId(customer.getId());
            dataCustomer.setStatus(ReportWorldStatusEnum.REPORT_NORMAL.getCode());
            dataCustomer.setAddUser(redisCacheManager.getLoginUserInfo().getLoginId());
            dataCustomer.setAddTime(LocalDateTime.now());
            dataCustomerMapper.update(dataCustomer, updateWrapper);
        }
        this.updateById(customer);
    }

    /**
     * 删除客户信息
     *
     * @param id
     * @throws Exception
     */
    public void delCustomer(String id) throws Exception {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("获取删除模块信息失败，请稍后重试！");
        }
        List<String> list = this.queryCustomerIds(id); //所有下级模块
        Customer oldCustomer = this.getById(id);
        // 删除的这个ID 不是一个一级的
        if ("0".equals(oldCustomer.getParentId())) {
            // 删除关联关系表中所所有改id包括所有下级的
            QueryWrapper<DataCustomer> wrapper = new QueryWrapper<>();
            wrapper.in("CUSTOMER_ID", list);
            dataCustomerMapper.delete(wrapper);
            this.removeByIds(list);
            return;
        }
        UpdateWrapper<DataCustomer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("CUSTOMER_ID", list);
        DataCustomer dataCustomer = new DataCustomer();
        dataCustomer.setCustomerId(oldCustomer.getParentId());
        dataCustomer.setStatus(ReportWorldStatusEnum.REPORT_NORMAL.getCode());
        dataCustomer.setAddUser(redisCacheManager.getLoginUserInfo().getLoginId());
        dataCustomer.setAddTime(LocalDateTime.now());
        dataCustomerMapper.update(dataCustomer, updateWrapper);
        this.removeByIds(list);
    }

    /**
     * 导出客户许可文件 Base64 加密  提供给升级工具使用
     */
    @Override
    public String customerBase64(Customer reportWorldCustomer) throws Exception {
        String[] includeProperties = {"id", "name", "status", "listModular", "listReport", "expireDate", "username", "password"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter includefilter = filters.addFilter();
        includefilter.addIncludes(includeProperties);
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        wrapper.eq("ID", reportWorldCustomer.getId());
        Customer customer = this.getOne(wrapper);
        if (null == customer) {
            throw new BusinessException("没有获取到客户信息，请稍后重试！");
        }
        if (StringUtils.isNotBlank(customer.getStrReport())) {
            customer.setListReport(JSONArray.parseArray(customer.getStrReport(), String.class));
        }
        if (StringUtils.isNotBlank(customer.getStrModular())) {
            customer.setListModular(JSONArray.parseArray(customer.getStrModular(), String.class));
        }
        //许可到期时间，默认一年时间
        customer.setExpireDate(DateUtil.dateToStr(DateUtil.addYear(new Date(), 1)));
        // 默认用户名密码
        customer.setUsername(ReportWorldEnum.USERNAME.getDesc());
        customer.setPassword(ReportWorldEnum.PASSWORD.getDesc());
        String jsonCustomer = JSONObject.toJSONString(customer, includefilter, SerializerFeature.WriteMapNullValue);
        // 使用基本型的编码器和解码器 对数据进行编码和解码
        //1.获取编码器
        Base64.Encoder encoder = Base64.getEncoder();
        //2.对字符串进行编码
        String strCustomer = encoder.encodeToString(jsonCustomer.getBytes());
        //4.获取解码器
        //  Base64.Decoder decoder = Base64.getDecoder();
        //5.对编码后的字符串进行解码
        //  byte[] decode = decoder.decode(strCustomer);
        //  String s1 = new String(decode);
        //  System.out.println("解码后的字符串："+s1);
        return strCustomer;
    }


    /**
     * 客户json格式信息
     */
    public String getCustomerJsonInfo() {
        String[] includeProperties = {"id", "name", "status"};
        PropertyPreFilters filters = new PropertyPreFilters();
        PropertyPreFilters.MySimplePropertyPreFilter includefilter = filters.addFilter();
        includefilter.addIncludes(includeProperties);
        List<Customer> list = this.list();
        return JSONObject.toJSONString(list, includefilter, SerializerFeature.WriteMapNullValue);
    }
}
